package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.domain.StrategyTemplate;
import cn.wolfcode.luowowo.search.query.SearchQueryObject;
import cn.wolfcode.luowowo.search.repository.StrategyTemplateRepository;
import cn.wolfcode.luowowo.search.service.IStrategyTemplateSearchService;
import cn.wolfcode.luowowo.search.vo.StatisVO;
import com.alibaba.dubbo.config.annotation.Service;
import com.sun.javafx.collections.MappingChange;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategyTemplateSearchServiceImpl implements IStrategyTemplateSearchService {

    //es 依然使用spring-data-jpa

    //repository 封装了template
    //template 封装了 client

    @Autowired
    private StrategyTemplateRepository repository;
//    @Autowired
//    private ElasticsearchTemplate template;
//    @Autowired
//    private TransportClient client;  //java操作es的第三方客户端


    @Override
    public void saveOrUpdate(StrategyTemplate template) {
        repository.save(template);
    }

    @Override
    public List<Map<String, Object>> getThemeCommend() {
        List<Map<String, Object>> data = new ArrayList<>();
        //步骤1:通过es分组查询,查询到主题推荐列表:themeid(主题id)themeName(主题名字)count
        //----------查询出所有主题-----------------------
        //分组列对象集合(id,name)
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();
        //分组查询中: id这个key
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
       // idSource.missingBucket(true);  //忽略不满足条件bucket
        idSource.field("themeId");
        sources.add(idSource);
        //分组查询中: id这个name
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        //nameSource.missingBucket(true);  //忽略不满足条件bucket
        nameSource.field("themeName");
        sources.add(nameSource);

        //参数1:分组查询结果名称   参数2:分组查询字段配置对象集合
        CompositeAggregationBuilder aggsBuilder = new CompositeAggregationBuilder("themeGroup", sources);

        //es查询语句构建类
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //明确指定查那个索引,那个类型
        //发起查询请求操作
        builder.addAggregation(aggsBuilder);  //聚合查询构建模块
        //分页
        builder.withPageable(PageRequest.of(0, 1));  //size = 0 因为pageable中的size不能为0, 只能使用1
        builder.withIndices(StrategyTemplate.INDEX_NAME);  //查询的索引
        builder.withTypes(StrategyTemplate.TYPE_NAME);  //查询类型

        //聚合查询结果
        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());
        //分组查询结果对象: buckets 封装对象
        InternalComposite aggregation = page.getAggregations().get("themeGroup");
        //结果封装
        List<StatisVO>  themes = new ArrayList<>();
        //遍历buckets
        for (CompositeAggregation.Bucket bucket : aggregation.getBuckets()) {
            long id = Long.parseLong(bucket.getKey().get("id").toString());
            String name = bucket.getKey().get("name").toString();
            long count = bucket.getDocCount();

            StatisVO vo = new StatisVO();
            vo.setId(id);
            vo.setName(name);
            vo.setCount(count);
            themes.add(vo);
        }

        //优化1: 排序, themes集合中根据DocCount大小排序, 此处使用倒序
        Collections.sort(themes, new Comparator<StatisVO>() {
            //返回结果是int类型
            //正数:表示大于
            //负数:表示小于
            //0  :表示等于
            @Override
            public int compare(StatisVO o1, StatisVO o2) {
               //倒序排
                Long result = o2.getCount() - o1.getCount();
                return result.intValue();
            }
        });

        //优化2: 截取前面10
        if (themes.size() > 10) {
            themes = themes.subList(0, 10);
        }

        //步骤2:通过主题id,查询目的地集合
//----------遍历所有主题查询该主题下所有目的地-----------------------
        Map<String, Object> map=null;
        for (StatisVO theme : themes) {
            //通过主题id查询主题下的所有目的地集合
            List<StatisVO> dests = this.getDestByThemeId(theme.getId());
            //左边: 注解vo  右边: 目的地集合(list<VO>)
            map = new HashMap<>();
            map.put("theme", theme);
            map.put("dests", dests);
            data.add(map);
        }
        //步骤3:通过步骤1,步骤2,数据,组装成最终的data(数据),并返回
        return data;
    }

    @Override
    public List<StatisVO> queryConditionChinas() {
        return this.getStatsVoList("provinceId","provinceName","provinceGroup");
    }

    @Override
    public List<StatisVO> queryConditionAbroad() {
        return this.getStatsVoList("countryId","countryName","countryGroup");
    }

    @Override
    public List<StatisVO> queryConditionTheme() {
        return this.getStatsVoList("themeId","themeName","themeGroup");
    }
//统计分组集合,抽取处来的重复方法
    private List<StatisVO> getStatsVoList(String idField,String nameField,String GroupField){
        //分组列对象集合(id,name)
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.field(idField);
        sources.add(idSource);
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        nameSource.field(nameField);
        sources.add(nameSource);
        //参数1:分组查询结果名称   参数2:分组查询字段配置对象集合
        CompositeAggregationBuilder aggsBuilder = new CompositeAggregationBuilder(GroupField, sources);
        //es查询语句构建类
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        //明确指定查那个索引,那个类型
        //发起查询请求操作
        builder.addAggregation(aggsBuilder);  //聚合查询构建模块
        //分页
        builder.withPageable(PageRequest.of(0, 1));  //size = 0 因为pageable中的size不能为0, 只能使用1
        builder.withIndices(StrategyTemplate.INDEX_NAME);  //查询的索引
        builder.withTypes(StrategyTemplate.TYPE_NAME);  //查询类型
        //聚合查询结果
        AggregatedPage<StrategyTemplate> page = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());
        //分组查询结果对象: buckets 封装对象
        InternalComposite aggregation = page.getAggregations().get(GroupField);
        //结果封装
        List<StatisVO>  themes = new ArrayList<>();
        //遍历buckets
        for (CompositeAggregation.Bucket bucket : aggregation.getBuckets()) {
            long id = Long.parseLong(bucket.getKey().get("id").toString());
            String name = bucket.getKey().get("name").toString();
            long count = bucket.getDocCount();
            StatisVO vo = new StatisVO();
            vo.setId(id);
            vo.setName(name);
            vo.setCount(count);
            themes.add(vo);
        }
        //优化1: 排序, themes集合中根据DocCount大小排序, 此处使用倒序
        Collections.sort(themes, new Comparator<StatisVO>() {
            @Override
            public int compare(StatisVO o1, StatisVO o2) {
                //倒序排
                Long result = o2.getCount() - o1.getCount();
                return result.intValue();
            }
        });
        return themes;
    }

    //通过主题id查询目的地
    private List<StatisVO> getDestByThemeId(Long themeId) {
        List<StatisVO> list = new ArrayList<>();
        List<StrategyTemplate> byThemeIds = repository.findByThemeId(themeId);
        //上面查询到 es攻略list集合,前面需要目的地id,name

        //优化3:目的地去重
        ArrayList<String> list1 = new ArrayList<>();
        for (StrategyTemplate te : byThemeIds) {
           if (!list1.contains(te.getDestName())){
               StatisVO vo = new StatisVO();
               vo.setId(te.getId());
               vo.setName(te.getDestName());
               list.add(vo);

               list1.add(te.getDestName());
           }
        }
        return list;
    }

    @Override
    public Page query(SearchQueryObject qo) {
        TermQueryBuilder query=null;
        PageRequest of = PageRequest.of(qo.getCurrentPage()-1, qo.getPageSize(),
                Sort.Direction.DESC, qo.getOrderBy());
        if(qo.getType() == SearchQueryObject.CONDITION_TYPE_COUNTRY){
            //countryId  国家
            query = QueryBuilders.termQuery("countryId", qo.getTypeValue());
        }else if(qo.getType() == SearchQueryObject.CONDITION_TYPE_PROVINCE){
            //provinceId  省份
            query = QueryBuilders.termQuery("provinceId", qo.getTypeValue());
        }else if(qo.getType() == SearchQueryObject.CONDITION_TYPE_THEME){
            //themeid     //主题
            query =  QueryBuilders.termQuery("themeId", qo.getTypeValue());
        }
        if(query==null){
            return repository.findAll(of);
        }else {
            return repository.search(query,of);
        }
    }

    @Override
    public List<StrategyTemplate> findByDestName(String destName) {
        return repository.findByDestName(destName);

    }
}
